package com.cqrt.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.hustcad.plm.pdm.core.base.EntityBase;
import com.hustcad.plm.pdm.core.base.TyppmLinkBase;
import com.hustcad.plm.pdm.core.handle.exception.SystemErrorCodeEnum;
import com.hustcad.plm.rpm.constant.ProjectMngConstant;
import com.hustcad.plm.rpm.entityconvert.BaseConvert;
import com.hustcad.plm.rpm.entityconvert.issue.ProjectChangeIssueLinkConvert;
import com.hustcad.plm.rpm.model.dto.issue.DeleteIssueLinkDTO;
import com.hustcad.plm.rpm.model.dto.remote.CheckRemoteParams;
import com.hustcad.plm.rpm.model.dto.remote.RemoteObjDTO;
import com.hustcad.plm.rpm.model.entity.issue.TyppmProjectChangeIssueLink;
import com.hustcad.plm.rpm.model.entity.remote.TyppmRemoteObject;
import com.hustcad.plm.rpm.service.impl.issue.TyppmProjectChangeIssueLinkServiceImpl;
import com.hustcad.plm.rpm.service.job.TyppmJobDeliverLinkService;
import com.hustcad.plm.rpm.service.job.TyppmJobService;
import com.hustcad.plm.rpm.service.outrule.TyppmOutRuleService;
import com.hustcad.plm.rpm.service.remote.HandlerRemoteService;
import com.hustcad.plm.rpm.service.remote.TyppmRemoteObjectIdService;
import com.hustcad.plm.rpm.service.remote.TyppmRemoteObjectInfoService;
import com.hustcad.plm.rpm.service.remoterequest.ThirdRemoteRequestService;
import com.ty.ppm.api.service.issue.ProjectChangeIssueLinkService;
import com.ty.ppm.model.entity.issue.ProjectChangeIssueLink;
import com.ty.ppm.model.utils.TyppmBatchQueryHelper;
import com.ty.ppm.service.mapper.issue.ProjectChangeIssueLinkMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Primary
@Slf4j
public class RTTyppmProjectChangeIssueLinkServiceImpl extends TyppmProjectChangeIssueLinkServiceImpl {
    @Resource
    private TyppmRemoteObjectIdService typpmRemoteObjectIdService;
    @Resource
    private TyppmRemoteObjectInfoService typpmRemoteObjectInfoService;
    @Resource
    private TyppmJobDeliverLinkService typpmJobDeliverLinkService;
    @Resource
    private ProjectChangeIssueLinkMapper projectChangeIssueLinkMapper;
    @Resource
    private BaseConvert baseConvert;
    @Resource
    private ProjectChangeIssueLinkService projectChangeIssueLinkService;
    @Resource
    private ThirdRemoteRequestService thirdRemoteRequestService;
    @Resource
    private TyppmOutRuleService typpmOutRuleService;
    @Transactional(
            rollbackFor = {Exception.class}
    )
    public void batchDeleteChangeIssueLink(DeleteIssueLinkDTO deleteIssueLink) {
        if (CollUtil.isEmpty(deleteIssueLink.getOidList())) {
            throw SystemErrorCodeEnum.ARGUMENT_NONE.message("oidList");
        } else if (ObjectUtils.isEmpty(deleteIssueLink.getDeleteFlag())) {
            throw SystemErrorCodeEnum.ARGUMENT_NONE.message("deleteFlag");
        } else {
            if (ProjectMngConstant.ISSUE_DELETE_PROJECT_LINK.equals(deleteIssueLink.getDeleteFlag())) {
                CheckRemoteParams checkRemote = new CheckRemoteParams();
                checkRemote.setLinkOidList(deleteIssueLink.getOidList());
                this.typpmRemoteObjectInfoService.batchDeleteRemoteObjectInfo(checkRemote, ProjectChangeIssueLink.class);
                this.updateMarkForDelete(deleteIssueLink.getOidList());
            } else {
                List<BigInteger> oidList = deleteIssueLink.getOidList().stream().map(BigInteger::new).collect(
                        Collectors.toList());
                List<ProjectChangeIssueLink> projectChangeIssueLinkDOS = this.projectChangeIssueLinkService.selectByOIDList(oidList);
                List<TyppmProjectChangeIssueLink> issueLinkList = projectChangeIssueLinkDOS.stream().map((issueLink) -> this.baseConvert.copyProperties(issueLink, TyppmProjectChangeIssueLink.class)).collect(Collectors.toList());
                List<String> issueLinkRemoteList = issueLinkList.stream().map(
                        TyppmLinkBase::getBRoleOID).collect(Collectors.toList());
                List<TyppmRemoteObject> remoteObjectList = this.typpmRemoteObjectIdService.selectByOIDList(issueLinkRemoteList);
                Map<String, List<TyppmRemoteObject>> remoteMap = remoteObjectList.stream().collect(Collectors.groupingBy(TyppmRemoteObject::getRemoteObjectId));
                List<TyppmRemoteObject> existRemoteObjects = this.typpmRemoteObjectIdService.listRemoteObjectIdByROIs(new ArrayList<>(remoteMap.keySet()));
                if (CollectionUtils.isEmpty(existRemoteObjects)) {
                    return;
                }

                Map<String, String> objRemoteMap = existRemoteObjects.stream().collect(Collectors.toMap(
                        EntityBase::getOid, TyppmRemoteObject::getRemoteObjectId, (a, b) -> b));
                List<BigInteger> collect = existRemoteObjects.stream().map((remoteObject) -> new BigInteger(remoteObject.getOid())).collect(Collectors.toList());
                Map<String, Object> params = new HashMap<>();
                params.put("projectOid", new BigInteger(deleteIssueLink.getProjectOid()));
                params.put("markfordelete", 0L);
                params.put("boid", collect);
                List<ProjectChangeIssueLink> projectChangeIssueLinkDoList = this.projectChangeIssueLinkService.listProjectChangeIssue(params);
                List<TyppmProjectChangeIssueLink> projectChangeIssueLinks = projectChangeIssueLinkDoList.stream().map((projectChangeIssueLinkDO) -> this.baseConvert.copyProperties(projectChangeIssueLinkDO, TyppmProjectChangeIssueLink.class)).collect(Collectors.toList());
                Map<String, List<TyppmProjectChangeIssueLink>> issueMap = projectChangeIssueLinks.stream().collect(Collectors.groupingBy((item) -> objRemoteMap.get(item.getBRoleOID())));
                List<String> realDelList = new ArrayList<>();

                for (Map.Entry<String, List<TyppmProjectChangeIssueLink>> stringListEntry : issueMap.entrySet()) {
                    Map.Entry<String, List<TyppmProjectChangeIssueLink>> entry =  stringListEntry;
                    List<TyppmProjectChangeIssueLink> value = entry.getValue();
                    List<String> tempLinkList = value.stream().map(EntityBase::getOid).collect(
                            Collectors.toList());
                    tempLinkList.forEach((item) -> {
                        if (deleteIssueLink.getOidList().contains(item) && tempLinkList.size() > 1) {
                            deleteIssueLink.getOidList().remove(item);
                            realDelList.add(item);
                        }
                    });
                }

                if (CollUtil.isNotEmpty(deleteIssueLink.getOidList())) {
                    deleteProjectJobLink(deleteIssueLink.getOidList());
                }

                if(CollUtil.isNotEmpty(remoteMap)){
                    deleteJobDeliverLink(remoteMap.keySet(), deleteIssueLink);
                }

                if (CollUtil.isNotEmpty(realDelList)) {
                    this.updateMarkForDelete2(realDelList);
                }
            }

        }
    }

    private void updateMarkForDelete2(List<String> oidList) {
        List<BigInteger> projectChangeissueLinkOidList = new ArrayList<>();
        for (String oid : oidList) {
            projectChangeissueLinkOidList.add(new BigInteger(oid));
        }
        projectChangeIssueLinkMapper.updateMarkForDelete(projectChangeissueLinkOidList);
    }

    private void deleteJobDeliverLink(Set<String> ids, DeleteIssueLinkDTO deleteIssueLink) {
        List<RemoteObjDTO> remoteObjDTOS = this.thirdRemoteRequestService.queryDeliverableByParent(
                deleteIssueLink.getJobOid(), deleteIssueLink.getJobOtype(), "IN", deleteIssueLink.getProjectOid());
        if(CollUtil.isNotEmpty(remoteObjDTOS)){
            List<String> oidList = remoteObjDTOS.stream().filter(item -> ids.contains(item.getVersionID())).map(
                    RemoteObjDTO::getLinkID).collect(Collectors.toList());
            List<String> RemoteObjID = remoteObjDTOS.stream().filter(item -> ids.contains(item.getVersionID())).map(
                    RemoteObjDTO::getRemoteObjID).collect(Collectors.toList());
            if(CollUtil.isNotEmpty(oidList)){
                this.typpmOutRuleService.deleteOutRuleAndDeliverLink(RemoteObjID);
                this.typpmJobDeliverLinkService.deleteJobDeliverLinkByOidList(oidList);
            }
        }
    }

    private void deleteProjectJobLink(List<String> oidList) {
        List<BigInteger> projectChangeissueLinkOidList = new ArrayList<>();
        for (String oid : oidList) {
            projectChangeissueLinkOidList.add(new BigInteger(oid));
        }
        projectChangeIssueLinkMapper.deleteJobLink(projectChangeissueLinkOidList);
    }
}
